package library

import (
	"encoding/json"
	"fmt"
	"golang.org/x/net/websocket"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

type ResultMsg struct {
	ResultType  int        `json:ResultType`
	ResultCode  string     `json:ResultCode`
	Description string     `json:Description`
	BookList    []BookInfo `json:BookList`
}
type RequestParam struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type WebServer struct {
	Port         int
	book         BookFiles
	cache        BookCache
	fileRootPath string
}

//创建WEB server 对象
func NewWebServer() *WebServer {
	//返回播放库切片
	return &WebServer{}
}

//web server 初始化函数
func (this *WebServer) Init(root string) {
	fmt.Println("starting book files service, please waiting ......")
	this.book = *NewBookFiles()

	//	rs := []rune(root)
	//	if rs != nil && string(rs[len(root)-1:len(root)]) != "/" {
	//		root += "/"
	//	}
	this.fileRootPath = root
	//fmt.Println("root path:" + root+"last str:",rs[len(root)-1])
	this.book.Init(root)
	fmt.Println("starting book cache service, please waiting ......")
	this.cache = *NewBookCache()
	this.cache.Init()
}

//search处理函数
func (this *WebServer) searchReq(w http.ResponseWriter, req *http.Request) {
	//获取参数
	req.ParseForm()
	io.WriteString(w, "dir=")
	if len(req.Form["dir"]) > 0 {
		io.WriteString(w, req.FormValue("dir"))
	}
	files := this.book.search("c:/tmp", "b", nil)
	retDesc := fmt.Sprintf("搜索数量:%d", len(files))
	fmt.Println(retDesc)
	//	io.WriteString(w, retDesc)
	//	for _, f := range files {
	//		fmt.Println(f.BookName)
	//		io.WriteString(w, f.BookName+"<br/>")
	//	}
	//json.Marshal()
	//io.WritingString(w)
	log.Println("Method:" + req.Method)
}

//下载请求处理函数
//请求URL例子：http://localhost:7102/down?dir=a/b&file=btv00.csv
func (this *WebServer) downBook(w http.ResponseWriter, r *http.Request) {
	//获取参数
	r.ParseForm()
	if len(r.Form["dir"]) > 0 && len(r.Form["file"]) > 0 {
		dir := r.FormValue("dir")
		file := r.FormValue("file")
		fmt.Println("param dir:" + dir)
		fmt.Println("param file:" + file)

		//去掉参数dir中的最后一个“/”
		rs := []rune(dir)
		//fmt.Println(string(rs[len(dir)-1:]))
		if len(rs) > 0 && string(rs[len(rs)-1:]) != "/" {
			dir += "/"
		}
		//拼接本地文件全路径
		localFile := this.fileRootPath + dir + file
		fmt.Println("server file path:" + localFile)
		//获取文件信息，判断文件是否存在和读取权限
		if _, err := os.Stat(localFile); err == nil {
			//设置http头为下载
			w.Header().Set("Content-Type", "application/octet-stream")
			w.Header().Set("Content-Disposition", "attachment; filename="+file)
			fmt.Println("starting download file:" + localFile + " ......")
			//下载文件
			http.ServeFile(w, r, localFile)
			fmt.Println("starting download file over.")
		} else {
			fmt.Println("file:"+localFile+", dose not exist!"+",error:", err)
		}

	} else {
		fmt.Println("param error!")
	}
}
func (this *WebServer) listReq(w http.ResponseWriter, r *http.Request) {
	var dir string
	//获取参数
	r.ParseForm()
	if len(r.Form["dir"]) > 0 {
		dir = r.FormValue("dir")
		fmt.Println("list func, dir=" + dir)
	}
	//测试数据
	books, _, _ := this.book.ViewPath(dir)
	//this.make([]BookInfo, 0)
	//	book := BookInfo{"文档/golang", "sssspdf", 898， 0}
	//books = append(books, BookInfo{"文档/golang", "sssspdf", 898, 0})
	//books = append(books, BookInfo{"文档/golang", "sssspdf", 898, 1})
	bytes, err := json.Marshal(&books)
	if err == nil {
		io.WriteString(w, string(bytes))
	} else {
		//空结果集
		io.WriteString(w, "[]")
	}
}

//设置请求地址URL路由
func (this *WebServer) SetHandle() {
	//列出本级目录的文件夹和内容
	http.HandleFunc("/list", this.listReq)
	//搜索请求
	http.HandleFunc("/search", this.searchReq)
	//下载请求
	http.HandleFunc("/down", this.downBook)
	//获取全局信息
	http.HandleFunc("/global", this.getGlobalReq)
}
func (this *WebServer) getGlobalReq(w http.ResponseWriter, r *http.Request) {
	bytes, err := json.Marshal(&this.book.Global)
	if err == nil {
		io.WriteString(w, string(bytes))
	} else {
		//空结果集
		io.WriteString(w, "[]")
	}
}
func (this *WebServer) WSHandler(ws *websocket.Conn) {

	fmt.Println("echo handler called！")
	//receive message from websocket connection
	//最大上传4K数据
	rcvText := make([]byte, 4096)
	n, err := ws.Read(rcvText)
	if err != nil {
		log.Fatal(err)
		return
	}
	//转换为字符串
	fmt.Println("rcv length:", n, ",text:", string(rcvText[:n]))
	//转换为对象
	param := []RequestParam{}
	byt := []byte(rcvText[:n])
	if err := json.Unmarshal(byt, &param); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("处理输入参数")
	path := ""
	pattern := ""
	for _, p := range param {
		fmt.Println("key=" + p.Key)
		if p.Key == "path" {
			path = p.Value
		} else if p.Key == "text" {
			pattern = p.Value
		}
	}
	fmt.Println("输入参数path:" + path + ",搜索文本:" + pattern)
	result := ResultMsg{0, "succ", "", nil}
	if len(pattern) == 0 {
		result.ResultType = 0
		result.Description = "请输入搜索的关键字"
	} else {
		//查询
		nano1 := time.Now().UnixNano()
		books := this.book.search(this.fileRootPath+path, pattern, ws)
		nano2 := time.Now().UnixNano()
		fmt.Printf("插叙结束，数据个数:%d,耗时：%f毫秒", len(books), (nano2-nano1)/1000000.0)
		//将查询结果整合到resultMsg结构中
		result.ResultType = 1
		result.Description = fmt.Sprintf("%d", (nano2-nano1)/1000000)
		result.BookList = books
	}
	bytes, _ := json.Marshal(&result)
	//输出到浏览器
	bytes, _ = json.Marshal(&result)
	ws.Write(bytes)

	//websocket 测试
	//ch := make(chan int)
	//go this.wsTask(param, ws, ch)
	//fmt.Println("result:", <-ch)

}

func (this *WebServer) wsTask(paramList []RequestParam, ws *websocket.Conn, ch chan int) {
	//通知消息
	result := ResultMsg{0, "succ", "", nil}
	for i := 0; i < 60*100; i++ {
		now := time.Now()
		sendText := now.Format("2006-01-02 15:04:05")
		//ws.Write([]byte(sendText))
		//通知消息
		result.ResultType = 0
		result.Description = "通知" + fmt.Sprintf("%d", i)
		bytes, _ := json.Marshal(&result)
		ws.Write(bytes)
		//数据消息
		result.ResultType = 1
		result.BookList = make([]BookInfo, 0)
		b := BookInfo{"Path", "BookName", 233, 1, 0, 0}
		b.BookName = "书名" + sendText
		result.BookList = append(result.BookList, b)
		bytes, _ = json.Marshal(&result)
		//输出
		bytes, _ = json.Marshal(&result)
		ws.Write(bytes)
		time.Sleep(1 * 10 * time.Millisecond)
	}
	ch <- 0
}

//启动web server
func (this *WebServer) Start(port int) {
	fmt.Println("starting web server, please waiting ......")
	this.Port = port
	fmt.Println("listen port:", this.Port)
	//设置静态文件路径
	fmt.Println("set static file path:" + http.Dir("./static/"))
	http.Handle("/", http.FileServer(http.Dir("./static/")))
	//设置url路由请求
	this.SetHandle()
	//启动websocket
	http.Handle("/websocket", websocket.Handler(this.WSHandler))
	//启动web server
	fmt.Println("Web server had started.")
	err := http.ListenAndServe(fmt.Sprintf(":%d", this.Port), nil)
	if err != nil {
		log.Fatal("http server is error.")
	}
}
